let N = {
  version: '1.0'
}
/*
 * @namespace Util
 *
 * Various utility functions, used by nsn do web ui.
 */
N.Util = {
  // @function extend(dest: Object, src?: Object): Object
  // Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter.
  extend: function (dest) {
    let i, j, len, src

    for (j = 1, len = arguments.length; j < len; j++) {
      src = arguments[j]
      for (i in src) {
        dest[i] = src[i]
      }
    }
    return dest
  },

  // @function create(proto: Object, properties?: Object): Object
  // Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
  create: Object.create || (function () {
    function F () {}
    return function (proto) {
      F.prototype = proto
      return new F()
    }
  })(),

  // @function formatNum(num: Number, digits?: Number): Number
  // Returns the number `num` rounded to `digits` decimals, or to 5 decimals by default.
  formatNum: function (num, digits) {
	if (num === null || num === 'null' || num === undefined) {
		return ''
	}
	if (typeof num === 'number') {
		return new Number(num).toFixed(digits)
	} else {
		return num
	}
  },

  // 加密，用于页面跳转、下钻时URL传参敏感信息
  encryption: function (code) {
	  if (code === null || code === '' || code === undefined) {
		  return code
	  }
	  code = code + ''
	  let c = String.fromCharCode(code.charCodeAt(0) + code.length)
	  for (let i = 1; i < code.length; i++) {
		  c += String.fromCharCode(code.charCodeAt(i) + code.charCodeAt(i - 1))
	  }
	  let str = ''
	  for (let i = 0; i < c.length; i++) {
		  str += c.charCodeAt(i).toString(16)
	  }
	  return str
  },

  // 解密，用于页面跳转、下钻时URL传参敏感信息
  decryption: function (code) {
	  if (code === null || code === '' || code === undefined) {
		  return code
	  }
	  code = code + ''
	  let str = ''
	  for (let i = 0; i < code.length / 2; i++) {
		  let s = parseInt(code.substr(i * 2, 2), 16)
		  str += String.fromCharCode(s)
	  }
	  let c = String.fromCharCode(str.charCodeAt(0) - str.length)
	  for (let i = 1; i < str.length; i++) {
		  c += String.fromCharCode(str.charCodeAt(i) - c.charCodeAt(i - 1))
	  }
	  return c
  },


  // formatDate(date,"yyyy-MM-dd HH:mm"); optput  "2015-10-14 16:50"
  formatDate: function (now, mask) {
    let d = now
    let zeroize = function (value, length) {
      if (!length) length = 2
      value = String(value)
      for (let i = 0, zeros = ''; i < (length - value.length); i++) {
        zeros += '0'
      }
      return zeros + value
    }

    return mask.replace(/"[^"]*"|'[^']*'|\b(?:d{1,4}|m{1,4}|yy(?:yy)?|([hHMstT])\1?|[lLZ])\b/g, function ($0) {
      switch ($0) {
        case 'd':
          return d.getDate()
        case 'dd':
          return zeroize(d.getDate())
        case 'ddd':
          return ['Sun', 'Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat'][d.getDay()]
        case 'dddd':
          return ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][d.getDay()]
        case 'M':
          return d.getMonth() + 1
        case 'MM':
          return zeroize(d.getMonth() + 1)
        case 'MMM':
          return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][d.getMonth()]
        case 'MMMM':
          return ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'][d.getMonth()]
        case 'yy':
          return String(d.getFullYear()).substr(2)
        case 'yyyy':
          return d.getFullYear()
        case 'h':
          return d.getHours() % 12 || 12
        case 'hh':
          return zeroize(d.getHours() % 12 || 12)
        case 'H':
          return d.getHours()
        case 'HH':
          return zeroize(d.getHours())
        case 'm':
          return d.getMinutes()
        case 'mm':
          return zeroize(d.getMinutes())
        case 's':
          return d.getSeconds()
        case 'ss':
          return zeroize(d.getSeconds())
        case 'l':
          return zeroize(d.getMilliseconds(), 3)
        case 'L':
          let m = d.getMilliseconds()
          if (m > 99) m = Math.round(m / 10)
          return zeroize(m)
        case 'tt':
          return d.getHours() < 12 ? 'am' : 'pm'
        case 'TT':
          return d.getHours() < 12 ? 'AM' : 'PM'
        case 'Z':
          return d.toUTCString().match(/[A-Z]+$/)
          // Return quoted strings with the surrounding quotes removed
        default:
          return $0.substr(1, $0.length - 2)
      }
    })
  },

  // @function trim(str: String): String
  // Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)
  trim: function (str) {
    return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '')
  },

  // @function splitWords(str: String): String[]
  // Trims and splits the string on whitespace and returns the array of parts.
  splitWords: function (str) {
    return N.Util.trim(str).split(/\s+/)
  },

  // @function setOptions(obj: Object, options: Object): Object
  // Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`.
  setOptions: function (obj, options) {
    if (!obj.hasOwnProperty('options')) {
      obj.options = obj.options ? N.Util.create(obj.options) : {}
    }
    for (let i in options) {
      obj.options[i] = options[i]
    }
    return obj.options
  },

  // @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String
  // Converts an object into a parameter URL string, e.g. `{a: "foo", b: "bar"}`
  // translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will
  // be appended at the end. If `uppercase` is `true`, the parameter names will
  // be uppercased (e.g. `'?A=foo&B=bar'`)
  getParamString: function (obj, existingUrl, uppercase) {
    let params = []
    for (let i in obj) {
      params.push((uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i]))
    }
    return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&')
  },
  queryString: function (val) {
    let uri = window.location.search
    let re = new RegExp('' + val + '=([^&?]*)', 'ig')
    return ((uri.match(re)) ? decodeURIComponent(uri.match(re)[0].substr(val.length + 1)) : null)
  },
  // @function template(str: String, data: Object): String
  // Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'`
  // and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string
  // `('Hello foo, bar')`. You can also specify functions instead of strings for
  // data values — they will be evaluated passing `data` as an argument.
  template: function (str, data) {
    return str.replace(N.Util.templateRe, function (str, key) {
      let value = data[key]

      if (value === undefined) {
        throw new Error('No value provided for variable ' + str)
      } else if (typeof value === 'function') {
        value = value(data)
      }
      return value
    })
  },

  templateRe: /\{ *([\w_\-]+) *\}/g,

  // @function isArray(obj): Boolean
  // Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray)
  isArray: Array.isArray || function (obj) {
    return (Object.prototype.toString.call(obj) === '[object Array]')
  },
  loadForm: function (form, data) {
    this.clearForm(form)
    let $form = $('#' + form)
    for (let name in data) {
      let val = data[name]
      let dom = $form.find('input[name="' + name + '"][type=radio], input[name="' + name + '"][type=checkbox]')
      if (dom.length) {
        dom.prop('checked', false)
        dom.each(function () {
          let v = $(this).val()
          if (v === String(val) || $.inArray(v, $.isArray(val) ? val : [val]) >= 0) {
            $(this).prop('checked', true)
          }
        })
      } else {
        $form.find('input[name="' + name + '"]').val(val)
        $form.find('textarea[name="' + name + '"]').val(val)
        $form.find('select[name="' + name + '"]').val(val)
      }
    }
  },
  clearForm: function (form) {
    let $form = $('#' + form)
    $('input,select,textarea', $form).each(function () {
      let t = this.type,
        tag = this.tagName.toLowerCase()
      if (t === 'text' || t === 'hidden' || t === 'password' || tag === 'textarea') {
        this.value = ''
      } else if (t === 'file') {
        let file = $(this)
        let newfile = file.clone().val('')
        newfile.insertAfter(file)
        file.remove()
      } else if (t === 'checkbox' || t === 'radio') {
        this.checked = false
      } else if (tag === 'select') {
        this.selectedIndex = -1
      }
    })
  },
  // 重新加载DataTable数据
  reloadData: function (dataTable) {
    $('#' + dataTable).DataTable().ajax.reload()
  },
  // form表单转json对象
  serializeJson: function (form) {
    let $form = $('#' + form)
    let serializeObj = {}
    let array = $form.serializeArray()
    $(array).each(function () {
      let value = N.Util.trim(this.value)
      if (serializeObj[this.name]) {
        if ($.isArray(serializeObj[this.name])) {
          serializeObj[this.name].push(value)
        } else {
          serializeObj[this.name] = [serializeObj[this.name], value]
        }
      } else {
        serializeObj[this.name] = value
      }
    })
    return serializeObj
  },
  // 校验是否整数
  chkInt: function (str) {
    let patrn = /^\d+$/
    return patrn.test(str)
  },
  // 校验是数字
  chkNum: function (str) {
    let patrn = /^[+-]?\d+(\.\d+)?$/
    return patrn.test(str)
  },
  num: function (num) {
    if (!N.DESENSITIZATION) { // 不脱敏
      return num
    }
    if (typeof num === 'number') {
      num = num.toString()
    }
    if (num.length === 11) {
      return num.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
    } else if (num.length === 13) {
      return num.replace(/(\d{5})\d{4}(\d{4})/, '$1****$2')
    } else if (num.length === 14) {
      return num.replace(/(\d{6})\d{4}(\d{4})/, '$1****$2')
    } else if (num.length === 15) {
      return num.replace(/(\d{7})\d{4}(\d{4})/, '$1****$2')
    } else if (num.length > 4) {
      return num.substr(0, num.length - 4) + '****'
    } else {
      let str = num.substr(0, 1)
      for (let i = 1; i < num.length; i++) {
        str += '*'
      }
      return str
    }
  },
  download: function (url, data, method) {
    // 获得url和data
    if (!url) {
      return
    }
    layer.load(1, { shade: [0.3, '#000'] })
  },
  setxxxximsi: function (obj) {
	  if (obj === null) {
			return ''
		}
		obj = obj + ''
		if (userSensitive === 0) {
			return obj
		}
		if (obj.length === 15 && obj.substr(0, 3) === '460') {
			return obj.substr(0, 5) + '****' + obj.substr(9, 15)
		} else {
			return obj
		}
  },
  setxxxxmsisdn: function (obj) {
	  if (obj === null) {
			return ''
		}
		obj = obj + ''
		if (userSensitive === 0) {
			return obj
		}
		if (obj.length === 13) {
			return obj.substr(0, 5) + '****' + obj.substr(9, 13)
		} else {
			return obj
		}
  },
  setxxxxnumber: function (obj) {
	  if (obj === null) {
			return ''
		}
		obj = obj + ''
		if (userSensitive === 0) {
			return obj
		}
		if (obj.length === 13) {
			return obj.substr(0, 5) + '****' + obj.substr(9, 13)
		} else if (obj.length === 15) {
			return obj.substr(0, 5) + '****' + obj.substr(9, 15)
		} else if (obj.length >= 4) {
			return obj.substr(0, obj.length - 4) + '****'
		} else if (obj.length === 4) {
			return '****'
		} else {
			return obj
		}
  },
  setxxxxci: function (obj) {
	  if (obj === null) {
			return ''
		}
		obj = obj + ''
		if (ciSensitive === 0) {
			return obj
		}
		if (obj.length >= 4) {
			return obj.substr(0, obj.length - 4) + '****'
		} else if (obj.length === 4) {
			return '****'
		} else {
			return obj
		}
  },

  getChromeVersion: function () {
	    let arr = navigator.userAgent.split(' ')
	    let chromeVersion = ''
	    for (let i = 0; i < arr.length; i++) {
	        if (/chrome/i.test(arr[i])) { chromeVersion = arr[i] }
	    }
	    if (chromeVersion) {
	        return Number(chromeVersion.split('/')[1].split('.')[0])
	    } else {
	        return false
	    }
	}
}
N.Class = function () {}
N.Class.extend = function (props) {
  // @function extend(props: Object): Function
  // [Extends the current class](#class-inheritance) given the properties to be included.
  // Returns a Javascript function that is a class constructor (to be called with `new`).
  let NewClass = function () {
    // call the constructor
    if (this.initialize) {
      this.initialize.apply(this, arguments)
    }
  }

  let parentProto = NewClass.__super__ = this.prototype

  let proto = N.Util.create(parentProto)
  proto.constructor = NewClass

  NewClass.prototype = proto

  // inherit parent's statics
  for (let i in this) {
    if (this.hasOwnProperty(i) && i !== 'prototype') {
      NewClass[i] = this[i]
    }
  }

  // mix static properties into the class
  if (props.statics) {
    N.Util.extend(NewClass, props.statics)
    delete props.statics
  }

  // mix includes into the prototype
  if (props.includes) {
    N.Util.extend.apply(null, [proto].concat(props.includes))
    delete props.includes
  }

  // merge options
  if (proto.options) {
    props.options = N.Util.extend(N.Util.create(proto.options), props.options)
  }

  // mix given properties into the prototype
  N.Util.extend(proto, props)

  return NewClass
}
// $(function() {
    // 使Highcharts主题配置生效
    // Highcharts.setOptions(N.Util.Highcharts_theme)
// })
export default {
  name: N
}
